home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / progs / thor / thor_api / parsemsg / parsemsg.c < prev    next >
C/C++ Source or Header  |  1996-08-05  |  29KB  |  1,254 lines

  1. /* parsemsg.c
  2.     Auto: smake -f src:bbsread/parsemsg/makefile
  3. */
  4.  
  5. #include <exec/types.h>
  6. #include <exec/memory.h>
  7. #include <exec/nodes.h>
  8. #include <exec/lists.h>
  9. #include <exec/semaphores.h>
  10. #include <libraries/dos.h>
  11. #include <dos/dostags.h>
  12. #include <utility/tagitem.h>
  13. #include <utility/date.h>
  14. #include <proto/exec.h>
  15. #include <proto/dos.h>
  16. #include <proto/utility.h>
  17.  
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include <ctype.h>
  21.  
  22. #include    <libraries/bbsread.h>
  23. #include <proto/bbsread.h>
  24.  
  25. #include <libraries/utgui.h>
  26. #include <proto/utgui.h>
  27.  
  28. #include <libraries/reqtools.h>
  29. #include <proto/reqtools.h>
  30.  
  31. #define ULONG_MAX        4294967295
  32. #define BUFLEN            250
  33. #define GRABLEN        100
  34. #define NAMELENGTH    31
  35. #define CSI "\x9b"
  36.  
  37. /*  Global structure to hold librarybases  */
  38. struct TaskData
  39. {
  40.     struct ExecBase *SysBase;
  41.     struct DosLibrary *DOSBase;
  42.     struct Library *UtilityBase;
  43.     struct Library *BBSReadBase;
  44.     struct Library *UTGuiBase;
  45.     struct BBSListItem *mybbs;
  46.     struct List *conflist;
  47.     struct List *farealist;
  48.     ULONG msgnr;
  49.     ULONG replyto;
  50.     TEXT from[NAMELENGTH];
  51.     TEXT to[NAMELENGTH];
  52.     TEXT confname[NAMELENGTH];
  53.     TEXT subject[NAMELENGTH];
  54.     BOOL private;
  55.     BOOL read;
  56.     ULONG time;
  57.     struct MinList linelist;
  58.     ULONG lines;
  59.     BPTR fh;
  60.     STRPTR errmsg;
  61.     APTR msgpool;
  62.     APTR confpool;
  63.     APTR pbar;
  64.     STRPTR pubscreen;
  65. };
  66.  
  67. #define SysBase        td->SysBase
  68. #define DOSBase        td->DOSBase
  69. #define UtilityBase    td->UtilityBase
  70. #define BBSReadBase    td->BBSReadBase
  71. #define UTGuiBase        td->UTGuiBase
  72. #define mybbs            td->mybbs
  73. #define conflist        td->conflist
  74. #define farealist        td->farealist
  75. #define msgnr            td->msgnr
  76. #define replyto        td->replyto
  77. #define from            td->from
  78. #define to                td->to
  79. #define confname        td->confname
  80. #define subject        td->subject
  81. #define private        td->private
  82. #define read            td->read
  83. #define time            td->time
  84. #define linelist        td->linelist
  85. #define lines            td->lines
  86. #define fh                td->fh
  87. #define errmsg            td->errmsg
  88. #define msgpool        td->msgpool
  89. #define confpool        td->confpool
  90. #define pbar            td->pbar
  91. #define pubscreen        td->pubscreen
  92.  
  93.  
  94. extern STRPTR progname, progdate;
  95. extern LONG version, revision;
  96.  
  97. /*  Prototypes for external functions  */
  98. extern void * __asm AsmCreatePool(register __d0 ULONG, register __d1 ULONG, register __d2 ULONG, register __a6 struct ExecBase *);
  99. extern void __asm AsmDeletePool(register __a0 void *, register __a6 struct ExecBase *);
  100. extern void * __asm AsmAllocPooled(register __a0 void *, register __d0 ULONG, register __a6 struct ExecBase *);
  101. extern void __asm AsmFreePooled(register __a0 void *, register __a1 void *, register __d0 ULONG, register __a6 struct ExecBase *);
  102.  
  103. extern APTR SPrintf(STRPTR dest, STRPTR fmtstr, ...);
  104. extern struct Library *OpenBRLibrary(struct ExecBase *, struct DosLibrary *, STRPTR, LONG);
  105.  
  106. /*  Prototypes for global functions  */
  107. struct Node * FindiName(struct List *list, STRPTR name);
  108. BOOL DoMsgAdding(struct TaskData *td);
  109. BOOL ParseConfList(struct TaskData *td);
  110. BOOL ParseFileList(struct TaskData *td);
  111. STRPTR MyStrTok(STRPTR *tokptr, STRPTR input);
  112. UBYTE *StripAnsi(UBYTE *s);
  113.  
  114. STRPTR monthnames[] = 
  115.     "January", "February", "March", 
  116.     "April", "May", "June", 
  117.     "July", "August", "September", 
  118.     "October", "November", "December" 
  119. };
  120.  
  121. UBYTE *template = "BBSNAME,GRAB,PUBSCREEN/K,ARCHIVE/S,DELETE/S,USAGE/S";
  122.  
  123. enum {
  124.     TEM_BBSNAME,
  125.     TEM_GRAB,
  126.     TEM_PUBSCREEN,
  127.     TEM_ARCHIVE,
  128.     TEM_DELETE,
  129.     TEM_USAGE,
  130.     TEM_NUMBEROF
  131. };
  132.  
  133. STRPTR fmtstr =
  134. "%s V%ld.%ld\n"
  135. "Usage: %s [bbsname] [grab] [PubScreen name] [ARCHIVE] [DELETE] [USAGE]\n"
  136. "Copyright © Ultima Thule Software %s  Author: Eivind Nordseth\n%s";
  137.  
  138. LONG __saveds NoName(void)
  139. {
  140.     struct TaskData TaskData, *td;
  141.     struct GlobalConfig *cfg = NULL;
  142.     struct ConfListItem *myconf;
  143.     struct RDArgs *rdargs = NULL, *args = NULL;
  144.     BOOL newmsg = FALSE, findsubject = FALSE, getlines = FALSE, bufCopyBack = FALSE, addedMsgs = FALSE;
  145.     LONG array[TEM_NUMBEROF], retval = RETURN_FAIL, len, filelen, filepos;
  146.     struct List *bbslist = NULL;
  147.     STRPTR strp, foo, grab = NULL;
  148.     struct MinNode *node;
  149.     TEXT buf[BUFLEN], grabname[GRABLEN], tmpfile[GRABLEN];
  150.     BPTR lock, tmpfh = NULL;
  151.     UWORD charset;
  152.     
  153.     setmem(td = &TaskData, sizeof(struct TaskData), 0);
  154.     SysBase = *(struct ExecBase **)4;
  155.  
  156.     if(!(DOSBase = (struct DosLibrary *) OpenLibrary(DOSNAME, 0L))) return(10000L);
  157.     if(DOSBase->dl_lib.lib_Version < 37)
  158.     {
  159.         errmsg = "Needs Kick V37+";
  160.         goto quit;
  161.     }
  162.     if(!(UtilityBase = OpenLibrary("utility.library", 37L))) goto quit;
  163.  
  164.     if(!(BBSReadBase = OpenBRLibrary(SysBase, DOSBase, BBSREADNAME, 3L)))
  165.     {
  166.         errmsg = "Needs bbsread.library V3+";
  167.         goto quit;
  168.     }
  169.  
  170.     UTGuiBase = OpenBRLibrary(SysBase, DOSBase, "utgui.library", 1L);
  171.  
  172.     if(!(args = AllocDosObject(DOS_RDARGS, NULL))) goto quit;
  173.     setmem(array, TEM_NUMBEROF * sizeof(LONG), 0);
  174.  
  175.     SPrintf(args->RDA_ExtHelp = buf, fmtstr, progname, version, revision, 
  176.         progname, progdate, template);
  177.  
  178.     if(!(rdargs = ReadArgs(template, array, args)))
  179.     {
  180.         errmsg = "Error in arguments.";
  181.         goto quit;
  182.     }
  183.  
  184.     if(array[TEM_USAGE] || !array[TEM_BBSNAME] || !array[TEM_GRAB]) 
  185.     {
  186.         Printf(fmtstr, progname, version, revision, progname, progdate, "");
  187.         retval = RETURN_OK;
  188.         goto quit;
  189.     }
  190.     
  191.     pubscreen = (STRPTR) array[TEM_PUBSCREEN];
  192.  
  193.     if(!(cfg = GetGlobalConfig())) { errmsg = "Error geting global config."; goto quit; }
  194.  
  195.     if(!(ConfigGlobalTags(cfg, CG_BufCopyBack, TRUE, TAG_END))) { errmsg = "Error changing global config."; goto quit; }
  196.     bufCopyBack = TRUE;
  197.         
  198.     if(!(bbslist = GetBBSList())) { errmsg = "Error geting bbslist."; goto quit; }
  199.  
  200.     if(!(mybbs = (struct BBSListItem *) FindiName(bbslist, (STRPTR) array[TEM_BBSNAME])))
  201.     {
  202.         errmsg = "Unknown BBS";
  203.         goto quit;
  204.     }
  205.     StartOfAdding(mybbs);
  206.  
  207.     if(mybbs->bl_Data->bd_Flags & BDF_ADD_USERS)
  208.     {
  209.         WriteBRUserTags(mybbs, WBRUSR_OnlyIfNotExist, TRUE, BRUSR_Name, "SYSOP", TAG_END);
  210.     }
  211.  
  212.     if(!(conflist = GetConfList(mybbs))) { errmsg = "Error geting conflist."; goto quit; }
  213.  
  214.     if(ParseConfList(td)) goto quit;
  215.     if(ParseFileList(td)) goto quit;
  216.  
  217.     if(!(confpool = AsmCreatePool(MEMF_ANY, 1024, 512, SysBase)))
  218.     {
  219.         errmsg = "Out of memory";
  220.         goto quit;
  221.     }
  222.  
  223.  
  224. /* Make a copy of all confnames in the correct conference charset. */
  225.  
  226.     myconf = (struct ConfListItem *) &conflist->lh_Head;
  227.     
  228.     while((myconf = (struct ConfListItem *)myconf->cl_Node.ln_Succ)->cl_Node.ln_Succ)
  229.     {
  230.         if((charset = ConfCharset(mybbs, myconf)) != BRCS_ISO) 
  231.         {
  232.             if(!(myconf->cl_Node.ln_Name = AsmAllocPooled(confpool, 
  233.                 strlen(myconf->cl_Node.ln_Name) + 1, SysBase))) 
  234.             {
  235.                 errmsg = "Out of memory";
  236.                 goto quit;
  237.             }
  238.             CharsetConvert(BRCS_ISO, charset, myconf->cl_Data->cd_Name, 
  239.                 myconf->cl_Node.ln_Name, 0);
  240.         }
  241.     }
  242.  
  243.     if(!(lock = Lock((STRPTR) array[TEM_GRAB], ACCESS_READ)))
  244.     {
  245.         errmsg = "No grabfile"; 
  246.         goto done;
  247.     }
  248.     UnLock(lock);
  249.  
  250.     if(array[TEM_ARCHIVE]) 
  251.     {
  252.         if(pubscreen && UTGuiBase)
  253.         {
  254.             if(!pbar)
  255.             {
  256.                 if(!(pbar = ugOpenProgressBar(progname, 
  257.                     PB_Total, 1, 
  258.                     PB_ScreenName, pubscreen, 
  259.                     PB_AbortText, "_Abort",
  260.                     PB_ProgressText, "Unarchiving grab",
  261.                     PB_ProgressCWidth, 23,
  262.                     TAG_END)))
  263.                 {
  264.                     errmsg = "Coundn't open progress bar";
  265.                     goto quit;
  266.                 }
  267.             }
  268.             else
  269.             {
  270.                 if(ugUpdateProgressBar(pbar,
  271.                     PB_Total, 1,
  272.                     PB_Current, 0,
  273.                     PB_ProgressText, "Unarchiving grab",
  274.                     TAG_END)) goto done;
  275.             }
  276.  
  277.             SPrintf(tmpfile, "t:ParseMsg.%08lx", FindTask(NULL));
  278.  
  279.             tmpfh = Open(tmpfile, MODE_NEWFILE);
  280.         }
  281.     
  282.         if(UnArchiveTags((STRPTR) array[TEM_GRAB], 
  283.             UA_DestDir, mybbs->bl_BBSPath, 
  284.             tmpfh ? SYS_Output : TAG_IGNORE, tmpfh,
  285.             TAG_END))
  286.         {
  287.             if(tmpfh)
  288.             {
  289.                 Seek(tmpfh, 0, OFFSET_BEGINNING);
  290.                 
  291.                 while(FGets(tmpfh, buf, BUFLEN - 1)) FPuts(Output(), buf);
  292.             }
  293.  
  294.             errmsg = "Couldn't unarchive archive";
  295.             goto quit;
  296.         }
  297.         
  298.         strncpy(grabname, mybbs->bl_BBSPath, GRABLEN);
  299.         AddPart(grabname, mybbs->bl_Data->bd_GrabName, GRABLEN);
  300.  
  301.         grab = grabname;
  302.     }
  303.     else     grab = (STRPTR) array[TEM_GRAB];
  304.     
  305.     if(fh) Close(fh);
  306.     if(!(fh = Open(grab, MODE_OLDFILE)))
  307.     {
  308.         errmsg = "Unable to open grabfile";
  309.         goto quit;
  310.     }
  311.     
  312.     Seek(fh, 0, OFFSET_END);
  313.     if((filelen = Seek(fh, 0, OFFSET_BEGINNING)) == -1)
  314.     {
  315.         errmsg = "Seek error";
  316.         goto quit;
  317.     }
  318.     filepos = 0;
  319.  
  320.     if(pubscreen && UTGuiBase)
  321.     {
  322.         if(!pbar)
  323.         {
  324.             if(!(pbar = ugOpenProgressBar(progname, 
  325.                 PB_Total, filelen, 
  326.                 PB_ScreenName, pubscreen, 
  327.                 PB_AbortText, "_Abort",
  328.                 PB_ProgressText, "Parsing messages",
  329.                 PB_ProgressCWidth, 23,
  330.                 TAG_END)))
  331.             {
  332.                 errmsg = "Coundn't open progress bar";
  333.                 goto quit;
  334.             }
  335.         }
  336.         else
  337.         {
  338.             if(ugUpdateProgressBar(pbar,
  339.                 PB_Total, filelen,
  340.                 PB_Current, filepos,
  341.                 PB_ProgressText, "Parsing messages",
  342.                 TAG_END)) goto done;
  343.         }
  344.     }
  345.     else PutStr(CSI "0 p\n\n\n\n");
  346.  
  347.     NewList((struct List *)&linelist);
  348.     if(!(msgpool = AsmCreatePool(MEMF_ANY, 1024, 512, SysBase)))
  349.     {
  350.         errmsg = "Out of memory";
  351.         goto quit;
  352.     }
  353.  
  354.     while(FGets(fh, buf, BUFLEN - 1))
  355.     {
  356.         filepos += strlen(buf);
  357.  
  358.         if(findsubject)
  359.         {
  360.             if(!strncmp(buf, "   Entered on ",14))
  361.             {
  362.                 struct ClockData cd[1];
  363.  
  364.                 setmem(cd, sizeof(struct ClockData), '\0');
  365.  
  366.                 if(!isdigit(*(strp = &buf[14]))) 
  367.                 {
  368.                     while(*strp != ' ') if(!*(++strp)) goto datefail;     /* Spool over ABBS day    */
  369.                     if(*strp) strp++;
  370.                 }
  371.  
  372.                 cd->mday = atol(strp);
  373.                 while(*strp != ' ') if(!*(++strp)) goto datefail;    /* Spool over date str    */
  374.  
  375.                 if(!*(foo = ++strp)) goto datefail;
  376.  
  377.                 while(*strp != ' ') if(!*(++strp)) goto datefail;    /* Spool over month str    */
  378.                 if(strp[-1] == ',') strp[-1] = '\0';
  379.                 *strp = '\0';
  380.  
  381.                 for(cd->month = 0; cd->month < 12; cd->month++)
  382.                     if(!strcmp(foo, monthnames[cd->month])) break;
  383.         
  384.                 if(cd->month++ == 12) goto datefail;
  385.                 
  386.                 if(!*(++strp)) goto datefail;
  387.  
  388.                 cd->year = atol(strp);
  389.  
  390.                 while(*strp != ' ') if(!*(++strp)) goto datefail;    /* Spool over year        */
  391.                 
  392.                 if(!strncmp(strp, " at ", 4))
  393.                 {
  394.                     strp += 4;
  395.                     strp[2] = '\0';
  396.                     strp[5] = '\0';
  397.                     cd->hour = atol(strp);
  398.                     cd->min = atol(strp + 3);    /* Calculate time        */
  399.                 }
  400.  
  401.                 time = Date2Amiga(cd);
  402. datefail:
  403.                 charset = 0;
  404.             }
  405.             if(!strncmp(buf, "   Reply to msg",15))
  406.             {
  407.                 strp = &buf[18];
  408.  
  409.                 while(*strp != '.') if(!*(strp++)) break;
  410.                 *strp = '\0';
  411.                 replyto = atol(&buf[18]);
  412.             }
  413.             if(!strncmp(buf, "Subject: ",9))
  414.             {
  415.                 stccpy(subject, &buf[9], NAMELENGTH);
  416.                 if(subject[strlen(subject) - 2] == '\r') subject[strlen(subject) - 2] = '\0';
  417.                 findsubject = FALSE;
  418.                 getlines = TRUE;
  419.                 lines = 0;
  420.                 FGets(fh, buf, BUFLEN - 1);
  421.                 filepos += strlen(buf);
  422.                 FGets(fh, buf, BUFLEN - 1);
  423.                 filepos += strlen(buf);
  424.                 continue;
  425.             }
  426.         }
  427.         if(newmsg) 
  428.         {
  429. /*            FPuts(Output(), buf);  */
  430.             
  431.             confname[0] = to[0] = from[0] = '\0';
  432.             msgnr = ULONG_MAX;
  433.             private = FALSE;
  434.             read = FALSE;
  435.             time = 0 ;
  436.  
  437.             strp = buf;
  438.             do 
  439.             {
  440.                 if(!*(++strp)) goto line1fail;
  441.                 while(*strp != ' ') if(!*(++strp)) goto line1fail;
  442.             } while(strncmp(strp, " message",8));
  443.  
  444.             *strp = '\0';
  445.  
  446.             stccpy(confname, buf, NAMELENGTH);
  447.  
  448.             while(*strp != '#') if(!*(++strp)) goto line1fail;
  449.  
  450.             if(!*(foo = ++strp)) goto line1fail;
  451.             while(*strp != ' ') if(!*(++strp)) goto line1fail;
  452.             *strp = '\0';
  453.             msgnr = atol(foo);
  454.  
  455.             while(*strp != ' ') if(!*(++strp)) goto line1fail;
  456.             if(!*(foo = ++strp)) goto line1fail;
  457.  
  458.             do 
  459.             {
  460.                 if(!*(++strp)) goto line1fail;
  461.                 while(*strp != ' ') if(!*(++strp)) goto line1fail;
  462.             } while(strncmp(strp, " to ",4));
  463.             *strp = '\0';
  464.             stccpy(from, foo, NAMELENGTH);
  465.  
  466.             if(strlen(++strp) <= 3) goto line1fail;
  467.             foo = strp + 3;
  468.  
  469.             *(strp = foo + strlen(foo) - 2) = '\0';
  470.  
  471.             if(*(--strp) == '.')
  472.             {
  473.                 *strp = '\0';
  474.                 
  475.                 while(*(--strp) == ')')
  476.                 {
  477.                     while(*(--strp) != '(' && strp > foo);
  478.                     if(*(strp) != '(') break;
  479.  
  480.                     if(!stricmp(strp, "(PRIVATE)")) private = TRUE;
  481.                     if(!strcmp(strp, "(read)")) read = TRUE; 
  482.  
  483.                     if(read || private) *(--strp) = '\0';
  484.                     else break;
  485.                 }
  486.             }
  487.             
  488.             stccpy(to, foo, NAMELENGTH);
  489.  
  490. line1fail:            
  491.             if(!confname[0]) stccpy(confname, "No Conf", NAMELENGTH); 
  492.             if(!to[0])       stccpy(to, "Unknown", NAMELENGTH);
  493.             if(!from[0])     stccpy(from, "Unknown", NAMELENGTH); 
  494.  
  495.             newmsg = FALSE;
  496.             findsubject = TRUE;
  497.         }
  498.  
  499.         len = strlen(buf);
  500.         if(buf[len > 2 ? len - 3 : 0] == '\r' && buf[len > 2 ? len - 2 : 1] == '\r') 
  501.         {
  502.             if(msgnr)
  503.             {
  504.                 if(DoMsgAdding(td)) 
  505.                 {
  506.                     errmsg = "Failure when adding message";
  507.                     goto quit;
  508.                 }
  509.                 NewList((struct List *)&linelist);
  510.                 AsmDeletePool(msgpool, SysBase);
  511.                 if(!(msgpool = AsmCreatePool(MEMF_CLEAR, 1024, 512, SysBase)))
  512.                 {
  513.                     errmsg = "Out of memory";
  514.                     goto quit;
  515.                 }
  516.                 addedMsgs = TRUE;
  517.             }
  518.             newmsg = TRUE;
  519.             getlines = FALSE;
  520.         }
  521.  
  522.         if(getlines)
  523.         {
  524.             if(!(node = (struct MinNode *) AsmAllocPooled(msgpool, sizeof(struct MinNode) + 80, SysBase)))
  525.             {
  526.                 errmsg = "Out of memory";
  527.                 goto quit;
  528.             }
  529.             strp = (STRPTR) &node[1];
  530.             stccpy(strp, buf, 80);
  531.             if(strp[strlen(strp) - 2] == '\r') strp[strlen(strp) - 2] = '\0';
  532.             AddTail((struct List *)&linelist, (struct Node *) node);
  533.             lines++;            
  534.         }
  535.         if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  536.         {
  537.             errmsg = "***Break";
  538.             goto done;
  539.         }
  540.         if(pbar) if(ugUpdateProgressBar(pbar, PB_Current, filepos, TAG_END)) goto done;
  541.     }
  542.     if(lines)
  543.     {
  544.         if(DoMsgAdding(td)) 
  545.         {
  546.             errmsg = "Failure when adding message";
  547.             goto quit;
  548.         }
  549.         addedMsgs = TRUE;
  550.     }
  551.  
  552.     if(fh) Close(fh);
  553.     fh = NULL;
  554.  
  555.     if(!addedMsgs) 
  556.     {
  557.         errmsg = "No messages to add";
  558.         goto quit;
  559.     }
  560.  
  561.     if(array[TEM_DELETE]) DeleteFile((STRPTR) array[TEM_GRAB]);
  562.  
  563. done:   /*  All stuff is done  */
  564.  
  565.     retval = RETURN_OK;
  566.  
  567.     Flush(Output());
  568.  
  569. quit:
  570.     if(pbar) ugCloseProgressBar(pbar);
  571.     else Write(Output(), CSI "1 p", 4); 
  572.  
  573.     if(tmpfh)
  574.     {
  575.         Close(tmpfh);
  576.         DeleteFile(tmpfile);
  577.     }
  578.  
  579.     if(errmsg)
  580.     {
  581.         struct ReqToolsBase *ReqToolsBase = NULL;
  582.  
  583.         if(pbar)
  584.         {
  585.             if(ReqToolsBase = (struct ReqToolsBase *) OpenLibrary(REQTOOLSNAME, 38))
  586.             {
  587.                 rtEZRequestTags(errmsg, "_OK", NULL, NULL, 
  588.                     RT_ReqPos, REQPOS_CENTERSCR,
  589.                     RT_PubScrName, pubscreen,
  590.                     RTEZ_ReqTitle, progname,
  591.                     RT_Underscore, '_',
  592.                     TAG_END);
  593.  
  594.                 CloseLibrary((struct Library *) ReqToolsBase);
  595.             }
  596.         }
  597.  
  598.         if(!ReqToolsBase)
  599.         {
  600.             Write(Output(), errmsg, strlen(errmsg));
  601.             Write(Output(), "\n", 1);
  602.         }
  603.     }
  604.     if(fh) Close(fh);
  605.     if(grab && array[TEM_ARCHIVE]) DeleteFile(grab);
  606.     if(cfg)
  607.     {
  608.         if(bufCopyBack) ConfigGlobalTags(cfg, CG_BufEndCopyBack, TRUE, TAG_END);
  609.         FreeBRObject(cfg);
  610.     }
  611.     if(mybbs) EndOfAdding(mybbs);
  612.  
  613.     if(bbslist)   FreeBRObject(bbslist);
  614.     if(conflist)  FreeBRObject(conflist);
  615.     if(farealist) FreeBRObject(farealist);
  616.  
  617.     if(rdargs) FreeArgs(rdargs);
  618.     if(args)   FreeDosObject(DOS_RDARGS, args);
  619.  
  620.     if(msgpool) AsmDeletePool(msgpool, SysBase);
  621.     if(confpool) AsmDeletePool(confpool, SysBase);
  622.     if(UTGuiBase)   CloseLibrary(UTGuiBase);
  623.     if(BBSReadBase) CloseLibrary(BBSReadBase);
  624.     if(UtilityBase) CloseLibrary(UtilityBase);
  625.     CloseLibrary((struct Library *) DOSBase);
  626.     return(retval);
  627. }
  628.  
  629.  
  630. struct Node * FindiName(
  631. struct List *list, 
  632. STRPTR name)
  633. {
  634.     struct Node *node = (struct Node *) &list->lh_Head;
  635.     
  636.     while((node = node->ln_Succ)->ln_Succ)
  637.     {
  638.         if(!stricmp(name, node->ln_Name)) return(node);
  639.     }
  640.     return(NULL);
  641. }
  642.  
  643. /*  returns error */
  644. BOOL DoMsgAdding(
  645. struct TaskData *td)
  646. {
  647.     struct ConfListItem *myconf;
  648.     ULONG n = 0L;
  649.     STRPTR *linearray;
  650.     struct MinNode *node;
  651.     BOOL error = TRUE;
  652.     UWORD charset;
  653.  
  654.     if(!lines) return(FALSE);
  655.  
  656.     if(!(myconf = (struct ConfListItem *) FindiName(conflist, confname)))
  657.     {
  658. /*        Printf("New conference!\n");  */
  659.  
  660.         if((charset = ConfCharset(mybbs, NULL)) != BRCS_ISO) 
  661.             if(!CharsetConvert(charset, BRCS_ISO, confname, NULL, 0L)) goto fail;
  662.  
  663.         if(!(myconf = ConfigConfTags(NULL, 
  664.             CC_ConfList, conflist, 
  665.             CC_AddToBBS, mybbs, 
  666.             CC_ConfName, confname, 
  667.             CC_SetConfFlags, CDF_MEMBER_OF,
  668.             TAG_END))) goto fail; 
  669.  
  670.         if(charset != BRCS_ISO) /* Convert conference name? */
  671.         {
  672.             if(!(myconf->cl_Node.ln_Name = AsmAllocPooled(confpool, 
  673.                 strlen(myconf->cl_Node.ln_Name) + 1, SysBase))) 
  674.             {
  675.                 errmsg = "Out of memory";
  676.                 goto fail;
  677.             }
  678.             CharsetConvert(BRCS_ISO, charset, myconf->cl_Data->cd_Name, 
  679.                 myconf->cl_Node.ln_Name, 0);
  680.         }
  681.     } 
  682.     else 
  683.     {
  684.         charset = ConfCharset(mybbs, myconf);
  685.  
  686.         if(!(myconf->cl_Data->cd_Flags & CDF_MEMBER_OF)) 
  687.             ConfigConfTags(myconf, CC_SetConfFlags, CDF_MEMBER_OF, TAG_END);
  688.     }
  689.  
  690.     if(!(linearray = AsmAllocPooled(msgpool, (lines + 1) * sizeof(STRPTR), SysBase))) return(TRUE);
  691.  
  692.     node = (struct MinNode *) &linelist.mlh_Head;
  693.     while((node = node->mln_Succ)->mln_Succ) 
  694.     {
  695.         linearray[n] = (STRPTR) &node[1]; 
  696.         if(charset != BRCS_ISO) CharsetConvert(charset, BRCS_ISO, linearray[n], NULL, 0);
  697.         n++;
  698. /*        Printf("line %ld of %ld:%s\n", n, lines, &node[1]); */
  699.     }
  700.     if(n) { linearray[--n] = NULL; }
  701.     if(n) { if(!strlen(linearray[--n])) linearray[n] = NULL; }
  702.  
  703.     if(charset != BRCS_ISO)
  704.     {
  705.         CharsetConvert(charset, BRCS_ISO, from, NULL, 0);    
  706.         CharsetConvert(charset, BRCS_ISO, to, NULL, 0);    
  707.         CharsetConvert(charset, BRCS_ISO, subject, NULL, 0);    
  708.     }
  709.     
  710.     if(!WriteBRMessageTags(myconf,
  711.         BRMSG_FromName, from,
  712.         (strcmp(to, "ALL") ? BRMSG_ToName : TAG_IGNORE), to,
  713.         BRMSG_OrginalNr, msgnr,
  714.         (replyto ? BRMSG_RefNr : TAG_IGNORE), replyto,
  715.         (time ? BRMSG_CreationDate : TAG_IGNORE), time,
  716.         BRMSG_Subject, subject,
  717.         BRMSG_Text, linearray,
  718.         WBRMSG_MarkMessage, TRUE,
  719.         WBRMSG_Private, private,
  720.         WBRMSG_Read, read,
  721.         TAG_END)) goto fail;
  722.  
  723.     if(mybbs->bl_Data->bd_Flags & BDF_ADD_USERS || private)
  724.     {
  725.         WriteBRUserTags(mybbs, WBRUSR_OnlyIfNotExist, TRUE, BRUSR_Name, from, TAG_END);
  726.  
  727.         if(strcmp(to, "ALL"))
  728.             WriteBRUserTags(mybbs, WBRUSR_OnlyIfNotExist, TRUE, BRUSR_Name, to, TAG_END);
  729.     }
  730.     error = FALSE;
  731.  
  732. fail:
  733.     if(!pbar || error)
  734.     {
  735.         if(!pbar) PutStr("\x9b\x34\x41");
  736.  
  737.         Printf("Conf: %-30.s\nMsgnr: %5.ld   Replyto: %5.ld\nFrom: %-30.s To: %-30.s\n", 
  738.             myconf->cl_Data->cd_Name, msgnr, replyto, from, to);
  739.         Printf("Subject: %-60.s\n", subject);
  740.     }
  741.     lines = 0; replyto = 0;
  742.     return(error);
  743. }
  744.  
  745. /****** parsemsg/ParseConfList ******************************************
  746. *
  747. *   NAME    
  748. *    ParseConfList -- Parses conference list.
  749. *
  750. *   SYNOPSIS
  751. *    error = ParseConfList( td )
  752. *
  753. *    BOOL ParseConfList( struct TaskData * );
  754. *
  755. *   FUNCTION
  756. *    Parses conferences.txt and updates the conference list for a bbs.
  757. *    Dependant of SysBase, DOSBase, UtilityBase, BBSReadBase, UTGuiBase,
  758. *    mybbs, pubscreen, pbar and conflist defined in the TaskData structure.
  759. *
  760. *   INPUTS
  761. *    td - TaskData structure.
  762. *
  763. *   RESULT
  764. *    error - Boolean.
  765. *        The errmsg field in TaskData may be set to point to an error
  766. *        message if the function fails.
  767. *
  768. *   EXAMPLE
  769. *
  770. *   NOTES
  771. *
  772. *   BUGS
  773. *
  774. *   SEE ALSO
  775. *
  776. ******************************************************************************
  777. *
  778. */
  779. BOOL ParseConfList(
  780. struct TaskData *td)
  781. {
  782.     struct ConfListItem *myconf, *nextconf;
  783.     struct PassConfListItem *passconf;
  784.     struct List list[1];
  785.     STRPTR foo, bits;
  786.     TEXT ct[BUFLEN], fname[GRABLEN];
  787.     BOOL bitdone, biterr, heading = TRUE, error = TRUE, delete = FALSE;
  788.     LONGBITS flags;
  789.     BPTR dofh = NULL;
  790.     APTR pool = NULL;
  791.     LONG filelen, filepos;
  792.  
  793.     strncpy(fname, mybbs->bl_BBSPath, GRABLEN);
  794.     strncat(fname, "conferences.txt", GRABLEN - strlen(fname));
  795.  
  796.     if(!(dofh = Open(fname, MODE_OLDFILE))) return(FALSE);
  797.     
  798.     Seek(dofh, 0, OFFSET_END);
  799.     if((filelen = Seek(dofh, 0, OFFSET_BEGINNING)) == -1)
  800.     {
  801.         errmsg = "Seek error";
  802.         goto fail;
  803.     }
  804.     filepos = 0;
  805.  
  806.     if(pubscreen && UTGuiBase)
  807.     {
  808.         if(!pbar)
  809.         {
  810.             if(!(pbar = ugOpenProgressBar(progname, 
  811.                 PB_Total, filelen, 
  812.                 PB_ScreenName, pubscreen, 
  813.                 PB_AbortText, "_Abort",
  814.                 PB_ProgressText, "Parsing conference list",
  815.                 PB_ProgressCWidth, 23,
  816.                 TAG_END)))
  817.             {
  818.                 errmsg = "Coundn't open progress bar";
  819.                 goto fail;
  820.             }
  821.         }
  822.         else
  823.         {
  824.             if(ugUpdateProgressBar(pbar,
  825.                 PB_Total, filelen,
  826.                 PB_Current, filepos,
  827.                 PB_ProgressText, "Parsing conference list",
  828.                 TAG_END)) goto done;
  829.         }
  830.     }
  831.     else PutStr(CSI"0 p\n");
  832.  
  833.     NewList(list);
  834.     if(!(pool = AsmCreatePool(MEMF_ANY, 512, 256, SysBase)))
  835.     {
  836.         errmsg = "Out of memory";
  837.         goto fail;
  838.     }
  839.  
  840.     while(FGets(dofh, ct, BUFLEN - 1))
  841.     {
  842.         filepos += strlen(ct);
  843.         StripAnsi(ct);
  844.  
  845.         if(heading)
  846.         {
  847.             if(!(strcmp(ct, "-----------------"))) heading = FALSE;
  848.             continue;
  849.         }
  850.         bits = ct;
  851.         while(*bits != ':') if(!*(++bits)) break;
  852.         if(!*bits) continue;
  853.  
  854.         *bits = '\0';
  855.         foo = bits++ - 1;
  856.  
  857.         while(foo > ct && *foo == ' ') *(foo--) = '\0';
  858.         if(foo == ct) continue;
  859.         
  860.         bitdone = FALSE;
  861.         biterr = FALSE;
  862.         flags = 0;
  863.         while(!bitdone)
  864.         {
  865.             foo = ++bits;
  866.             
  867.             while(*foo && *foo != '.' && *foo != ',') foo++;
  868.             if(!*foo) 
  869.             {
  870.                 biterr = TRUE;
  871.                 break;
  872.             }
  873.             if(*foo == '.') bitdone = TRUE;
  874.             *(foo++) = '\0';
  875.             
  876.             if(!strcmp(bits, "MAIL"))            flags |= CDF_MAIL;
  877.             if(!strcmp(bits, "READ ONLY"))       flags |= CDF_READ_ONLY;
  878.             if(!strcmp(bits, "Obligatory"))      flags |= CDF_COMPULSORY;
  879.             if(!strcmp(bits, "FILE INFO"))       flags |= CDF_FILE_INFO;
  880.             if(!strcmp(bits, "USER INFO"))       flags |= CDF_USER_INFO;
  881.             if(!strcmp(bits, "Private allowed")) flags |= CDF_PRIVATE_ALLOWED;
  882.             if(!strcmp(bits, "Member"))          flags |= CDF_MEMBER_OF;
  883.             if(!strcmp(bits, "Alias"))           flags |= CDF_ALIAS | CDF_ENTER_ONLY_TO_ALL;
  884.             bits = foo;
  885.         }
  886.         if(biterr) continue;
  887.         
  888.         if(!(passconf = AsmAllocPooled(pool, sizeof(struct PassConfListItem) + strlen(ct) + 1, SysBase)))
  889.         {
  890.             errmsg = "Out of memory";
  891.             goto fail;
  892.         }
  893.         strcpy(passconf->pl_Name = passconf->pl_Node.ln_Name = (STRPTR) &passconf[1], ct);
  894.         passconf->pl_Description = NULL;
  895.         passconf->pl_BBSConfNr   = -1;
  896.         passconf->pl_Flags       = flags;
  897.         AddTail(list, (struct Node *) passconf);
  898.  
  899.         if(!pbar)
  900.         {
  901.             PutStr(CSI "A");
  902.             Printf("Conf: %-30.s, Flags: %l08x\n", ct, flags);
  903.         }
  904.  
  905.         if((myconf = (struct ConfListItem *) FindiName(conflist, ct)) || (flags & CDF_MEMBER_OF))
  906.         {
  907.             if(!(myconf = ConfigConfTags(myconf, CC_ConfList, conflist, 
  908.                 CC_AddToBBS, mybbs, CC_ConfName, ct, CC_ClearConfFlags, 
  909.                 CDF_MEMBER_OF | CDF_MAIL | CDF_READ_ONLY | CDF_COMPULSORY | CDF_FILE_INFO 
  910.                 | CDF_USER_INFO | CDF_PRIVATE_ALLOWED | CDF_ENTER_ONLY_TO_ALL | CDF_ALIAS
  911.                 | CDF_NOT_ON_BBS | CDF_REPLY_ONLY_TO_ALL | CDF_NO_LINEWRAP_DISPLAY, 
  912.                 CC_SetConfFlags, flags, TAG_END)))
  913.             {
  914.                 if(pbar) Printf("Conf: %-30.s, Flags: %l08x\n", ct, flags);
  915.     
  916.                 errmsg = "ConfigConf() failed";
  917.                 goto fail;
  918.             }
  919.             myconf->cl_UserData = (APTR) TRUE;
  920.         }
  921.         if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  922.         {
  923.             errmsg = "***Break";
  924.             goto done;
  925.         }
  926.         if(pbar) if(ugUpdateProgressBar(pbar, PB_Current, filepos, TAG_END)) goto done;
  927.     }
  928.  
  929.     nextconf = (struct ConfListItem *) conflist->lh_Head;
  930.  
  931.     while(nextconf = (struct ConfListItem *) (myconf = nextconf)->cl_Node.ln_Succ)
  932.     {
  933.         struct ConfInternal *confint = myconf->cl_Internal;
  934.  
  935.         if(confint->ci_LastMsg < confint->ci_FirstMsg  
  936.             && (!(myconf->cl_Data->cd_Flags & CDF_MEMBER_OF) || !myconf->cl_UserData))
  937.         {
  938.             ConfigConfTags(myconf, CC_DeleteConf, TRUE, TAG_END);
  939.         }
  940.         else 
  941.         {
  942.             if(!myconf->cl_UserData) 
  943.                 ConfigConfTags(myconf, 
  944.                     CC_SetConfFlags, CDF_NOT_ON_BBS, 
  945.                     CC_ClearConfFlags, CDF_MEMBER_OF, 
  946.                     TAG_END);
  947.         }
  948.     }
  949.  
  950.     if(WritePassiveConfList(mybbs, list))
  951.     {
  952.         errmsg = "WritePassiveConfList() failed";
  953.         goto fail;
  954.     }
  955.  
  956.     delete = TRUE;
  957. done:
  958.     error = FALSE;
  959. fail:
  960.     if(pool) AsmDeletePool(pool, SysBase);
  961.     if(dofh) Close(dofh);
  962.     if(delete) DeleteFile(fname);
  963.  
  964.     return(error);
  965. }
  966.  
  967. /****** parsemsg/ParseFileList ******************************************
  968. *
  969. *   NAME    
  970. *    ParseFileList -- Adds files from newfiles.txt to the file database.
  971. *
  972. *   SYNOPSIS
  973. *    error = ParseFileList( td )
  974. *
  975. *    BOOL ParseFileList( struct TaskData * );
  976. *
  977. *   FUNCTION
  978. *    Parses newfiles.txt and adds new files to the database. Dependant of
  979. *    SysBase, DOSBase, UtilityBase, BBSReadBase, UTGuiBase, mybbs,
  980. *    pubscreen, pbar and farealist defined in the TaskData structure.
  981. *
  982. *   INPUTS
  983. *    td - TaskData structure.
  984. *
  985. *   RESULT
  986. *    error - Boolean.
  987. *        The errmsg field in TaskData may be set to point to an error
  988. *        message if the function fails.
  989. *
  990. *   EXAMPLE
  991. *
  992. *   NOTES
  993. *
  994. *   BUGS
  995. *
  996. *   SEE ALSO
  997. *
  998. ******************************************************************************
  999. *
  1000. */
  1001. BOOL ParseFileList(
  1002. struct TaskData *td)
  1003. {
  1004.     struct FAreaListItem *farea = NULL;
  1005.     struct SFileResult *found;
  1006.     struct ClockData cd[1];
  1007.     TEXT ct[BUFLEN], fname[GRABLEN];
  1008.     BOOL error = TRUE, back = FALSE;
  1009.     STRPTR file, date, kb, min, dlds, descr[2], np;
  1010.     BPTR dofh = NULL;
  1011.     LONG cnt, filelen, filepos;
  1012.  
  1013.     strncpy(fname, mybbs->bl_BBSPath, GRABLEN);
  1014.     AddPart(fname, "Newfiles.txt", GRABLEN);
  1015.  
  1016.     if(!(dofh = Open(fname, MODE_OLDFILE))) return(FALSE);
  1017.     
  1018.     Seek(dofh, 0, OFFSET_END);
  1019.     if((filelen = Seek(dofh, 0, OFFSET_BEGINNING)) == -1)
  1020.     {
  1021.         errmsg = "Seek error";
  1022.         goto fail;
  1023.     }
  1024.  
  1025.     if(FGets(dofh, ct, BUFLEN - 1)) 
  1026.     {
  1027.         if(!strcmp(ct, "DONE\n")) goto done;
  1028.     }
  1029.     filepos = 5;
  1030.  
  1031.     if(pubscreen && UTGuiBase)
  1032.     {
  1033.         if(!pbar)
  1034.         {
  1035.             if(!(pbar = ugOpenProgressBar(progname, 
  1036.                 PB_Total, filelen, 
  1037.                 PB_ScreenName, pubscreen, 
  1038.                 PB_AbortText, "_Abort",
  1039.                 PB_ProgressText, "Parsing newfiles",
  1040.                 PB_ProgressCWidth, 23,
  1041.                 TAG_END)))
  1042.             {
  1043.                 errmsg = "Coundn't open progress bar";
  1044.                 goto fail;
  1045.             }
  1046.         }
  1047.         else
  1048.         {
  1049.             if(ugUpdateProgressBar(pbar,
  1050.                 PB_Total, filelen,
  1051.                 PB_Current, filepos,
  1052.                 PB_ProgressText, "Parsing newfiles",
  1053.                 TAG_END)) goto done;
  1054.         }
  1055.     }
  1056.     else PutStr(CSI"0 p\n");
  1057.  
  1058.     if(!(farealist = GetFAreaList(mybbs))) 
  1059.     { 
  1060.         errmsg = "GetFAreaList() failed";
  1061.         goto fail;
  1062.     }
  1063.  
  1064.     while(FGets(dofh, ct, BUFLEN - 1))
  1065.     {
  1066.         BOOL notdigit = FALSE;
  1067.  
  1068.         filepos += strlen(ct);
  1069.         StripAnsi(ct);
  1070.  
  1071.         if(ct[0] == '(')
  1072.         {
  1073.             LONG len = strlen(ct) - 1;
  1074.             
  1075.             if(ct[len] != ')') continue;
  1076.  
  1077.             if(len > 1) 
  1078.             {
  1079.                 ct[len] = '\0';
  1080.                 
  1081.                 strcpy(fname, &ct[1]);
  1082.                 
  1083.                 if(!(farea = (struct FAreaListItem *) FindiName(farealist, fname)))
  1084.                 {
  1085.                     if(!(farea = ConfigFAreaTags(NULL, 
  1086.                         CFA_FAreaList, farealist,
  1087.                         CFA_AddToBBS, mybbs,
  1088.                         CFA_Name, fname, TAG_END))) 
  1089.                     { 
  1090.                         errmsg = "ConfigFArea() failed"; 
  1091.                         goto fail;
  1092.                     }
  1093.                 }
  1094.                 cnt = 3;        /* Skip farea header */
  1095.             }
  1096.             else farea = NULL;
  1097.  
  1098.             continue;
  1099.         }
  1100.         if(!farea) continue;
  1101.         if(cnt) if(cnt--) continue;
  1102.         
  1103.         if(strlen(ct) < 40) continue;
  1104.         
  1105.         if(!(np = MyStrTok(&file, &ct[2])))   continue;
  1106.         if(!(np = MyStrTok(&date, np)))       continue;
  1107.         if(!(np = MyStrTok(&kb, np)))         continue;
  1108.         if(!(np = MyStrTok(&min, np)))        continue;
  1109.         if(!(descr[0] = MyStrTok(&dlds, np))) continue;
  1110.         descr[1] = NULL;
  1111.         
  1112.         for(np = date; *np; np++) 
  1113.             if(!isdigit(*np)) 
  1114.                 notdigit = TRUE;
  1115.  
  1116.         if(!isdigit(*kb)) notdigit = TRUE;
  1117.  
  1118.         if(!isdigit(*min)) notdigit = TRUE;
  1119.  
  1120.         for(np = dlds; *np; np++)  
  1121.             if(!isdigit(*np)) 
  1122.                 notdigit = TRUE;
  1123.  
  1124.         if(SetSignal(0L,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)
  1125.         {
  1126.             errmsg = "***Break";
  1127.             goto done;
  1128.         }
  1129.         if(pbar) if(ugUpdateProgressBar(pbar, PB_Current, filepos, TAG_END)) goto done;
  1130.  
  1131.         if(!descr[0] || notdigit) continue;
  1132.  
  1133.         if(found = SearchBRFileTags(
  1134.             SBRF_SearchFAreaList, farealist,
  1135.             SBRF_SearchStr, file,
  1136.             SBRF_SearchName, TRUE,
  1137.             SBRF_SearchAll, FALSE,
  1138.             TAG_END))
  1139.         {
  1140.             if(found->fr_FilesFound)
  1141.             {
  1142.                 if(found->fr_Files[0].ff_FArea == farea) 
  1143.                 {
  1144.                     APTR obj;
  1145.                     struct TagItem *tags;
  1146.                     BOOL equal = FALSE;
  1147.  
  1148.                     if(obj = ReadBRFileTags(found->fr_Files[0].ff_FArea, found->fr_Files[0].ff_FileNr,
  1149.                         RBRF_FileTagsPtr, &tags, TAG_END))
  1150.                     {
  1151.                         if(atol(dlds) == GetTagData(BRFILE_Downloads, 0, tags)) equal = TRUE;
  1152.                         FreeBRObject(obj);
  1153.                     }
  1154.                     if(equal == TRUE) continue;
  1155.                 }
  1156.             
  1157.                 WriteBRFileTags(farea, 
  1158.                     WBRF_UpdateFileNr, found->fr_Files[0].ff_FileNr,
  1159.                     WBRF_DeleteFile, TRUE,
  1160.                     TAG_END);
  1161.             }
  1162.             FreeBRObject(found);
  1163.         }
  1164.  
  1165.         setmem(cd, sizeof(struct ClockData), '\0');
  1166.         cd->mday = atol(&date[4]);
  1167.         date[4] = '\0';
  1168.         cd->month = atol(&date[2]);
  1169.         date[2] = '\0';
  1170.         cd->year = atol(date);
  1171.         if(cd->year < 78) cd->year += 2000;
  1172.         else cd->year += 1900;
  1173.  
  1174.         time = Date2Amiga(cd);
  1175.  
  1176.         if(!pbar)
  1177.         {
  1178.             if(back) PutStr(CSI "2A"); 
  1179.             back = TRUE;
  1180.  
  1181.             Printf("Farea: %-20.s File:%-16.s\nDescr: %-40.s\n", 
  1182.                 farea->al_Data->ad_Name, file, descr[0]);
  1183.         }
  1184.  
  1185.         if(!WriteBRFileTags(farea, 
  1186.             BRFILE_Name, file,
  1187.             BRFILE_Date, time, 
  1188.             BRFILE_Size, atol(kb) * 1024,
  1189.             BRFILE_Downloads, atol(dlds),
  1190.             BRFILE_Description, descr, TAG_END))
  1191.         { 
  1192.             if(pbar) Printf("Farea: %-20.s File:%-16.s\nDescr: %-40.s\n", 
  1193.                             farea->al_Data->ad_Name, file, descr[0]);
  1194.  
  1195.             errmsg = "WriteBRFile() failed"; 
  1196.             goto fail;
  1197.         }
  1198.     }
  1199.  
  1200.     Seek(dofh, 0 , OFFSET_BEGINNING);
  1201.     FPuts(dofh, "DONE\n"); 
  1202.  
  1203. done:
  1204.     error = FALSE;
  1205. fail:
  1206.     if(dofh) Close(dofh);
  1207.     
  1208.     return(error);
  1209. }
  1210.  
  1211. STRPTR MyStrTok(
  1212. STRPTR *tokptr,
  1213. STRPTR input)
  1214. {
  1215.     *tokptr = NULL;
  1216.     if(!input) return(NULL);
  1217.  
  1218.     while(*input && *input == ' ') input++;
  1219.     if(!*input) return(NULL);
  1220.  
  1221.     *tokptr = input;
  1222.     while(*input && *input != ' ') input++;
  1223.  
  1224.     if(!*input) return(NULL);
  1225.  
  1226.     *input = '\0';
  1227.     
  1228.     return(input + 1);
  1229. }
  1230.  
  1231. UBYTE *StripAnsi(UBYTE *s)
  1232. {
  1233.     STRPTR dest = s, d = s;
  1234.     
  1235.     while(*s)    
  1236.     {
  1237.         if((*s == 0x1b) || (*s == 0x9b))
  1238.         {
  1239.             if(*s == 0x1b)
  1240.             {
  1241.                 if(*++s != '[') continue;
  1242.             }
  1243.             s++;
  1244.             while(*s && *s < '@') s++;
  1245.         }
  1246.         else if(*s >= 32) *d++ = *s;
  1247.         s++;
  1248.     }
  1249.     *d = '\0';
  1250.  
  1251.     return(dest);
  1252. }
  1253.